import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score

# 设置中文显示
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']  # 或 'Heiti SC', 'Hiragino Sans GB'
plt.rcParams['axes.unicode_minus'] = False

# 读取CSV数据
def load_data(file_path):
    df = pd.read_csv(file_path)
    return df

# 计算评估指标
def calculate_metrics(y_true, y_pred):
    mae = mean_absolute_error(y_true, y_pred)
    rmse = np.sqrt(mean_squared_error(y_true, y_pred))
    r2 = r2_score(y_true, y_pred)
    return {
        'MAE': mae,
        'RMSE': rmse,
        'R²': r2
    }

# 绘制预测值与目标值对比图
def plot_prediction_vs_target(df, save_path=None):
    plt.figure(figsize=(12, 6))
    plt.plot(df['index'], df['target'], 'b-', label='目标值')
    plt.plot(df['index'], df['prediction'], 'r-', label='预测值')
    plt.xlabel('样本索引')
    plt.ylabel('值')
    plt.title('预测值与目标值对比')
    plt.legend()
    plt.grid(True, alpha=0.3)
    
    if save_path:
        plt.savefig(f"{save_path}/prediction_vs_target.png", dpi=300, bbox_inches='tight')
    plt.show()

# 绘制误差分布图
def plot_error_distribution(df, save_path=None):
    plt.figure(figsize=(12, 6))
    
    # 左边的直方图
    plt.subplot(1, 2, 1)
    sns.histplot(df['error'], kde=True, bins=30)
    plt.xlabel('误差')
    plt.ylabel('频数')
    plt.title('误差分布直方图')
    
    # 右边的箱线图
    plt.subplot(1, 2, 2)
    sns.boxplot(y=df['error'])
    plt.ylabel('误差')
    plt.title('误差箱线图')
    
    plt.tight_layout()
    
    if save_path:
        plt.savefig(f"{save_path}/error_distribution.png", dpi=300, bbox_inches='tight')
    plt.show()

# 绘制误差随索引的变化
def plot_error_by_index(df, save_path=None):
    plt.figure(figsize=(12, 6))
    plt.scatter(df['index'], df['error'], alpha=0.5)
    plt.axhline(y=0, color='r', linestyle='-', alpha=0.3)
    plt.xlabel('样本索引')
    plt.ylabel('误差')
    plt.title('误差随样本索引的变化')
    plt.grid(True, alpha=0.3)
    
    if save_path:
        plt.savefig(f"{save_path}/error_by_index.png", dpi=300, bbox_inches='tight')
    plt.show()

# 绘制预测值与目标值的散点图
def plot_prediction_target_scatter(df, save_path=None):
    plt.figure(figsize=(8, 8))
    plt.scatter(df['target'], df['prediction'], alpha=0.5)
    
    # 添加对角线（完美预测线）
    min_val = min(df['target'].min(), df['prediction'].min())
    max_val = max(df['target'].max(), df['prediction'].max())
    plt.plot([min_val, max_val], [min_val, max_val], 'r--', label='理想预测线')
    
    plt.xlabel('目标值')
    plt.ylabel('预测值')
    plt.title('预测值与目标值散点图')
    plt.grid(True, alpha=0.3)
    plt.legend()
    
    if save_path:
        plt.savefig(f"{save_path}/prediction_target_scatter.png", dpi=300, bbox_inches='tight')
    plt.show()

# 打印统计摘要
def print_summary_statistics(df):
    print("\n===== 数据统计摘要 =====")
    print(f"样本数量: {len(df)}")
    print(f"\n预测值统计:")
    print(f"  均值: {df['prediction'].mean():.4f}")
    print(f"  中位数: {df['prediction'].median():.4f}")
    print(f"  标准差: {df['prediction'].std():.4f}")
    print(f"  最小值: {df['prediction'].min():.4f}")
    print(f"  最大值: {df['prediction'].max():.4f}")
    
    print(f"\n目标值统计:")
    print(f"  均值: {df['target'].mean():.4f}")
    print(f"  中位数: {df['target'].median():.4f}")
    print(f"  标准差: {df['target'].std():.4f}")
    print(f"  最小值: {df['target'].min():.4f}")
    print(f"  最大值: {df['target'].max():.4f}")
    
    print(f"\n误差统计:")
    print(f"  均值: {df['error'].mean():.4f}")
    print(f"  中位数: {df['error'].median():.4f}")
    print(f"  标准差: {df['error'].std():.4f}")
    print(f"  最小值: {df['error'].min():.4f}")
    print(f"  最大值: {df['error'].max():.4f}")
    
    metrics = calculate_metrics(df['target'], df['prediction'])
    print(f"\n评估指标:")
    print(f"  MAE (平均绝对误差): {metrics['MAE']:.4f}")
    print(f"  RMSE (均方根误差): {metrics['RMSE']:.4f}")
    print(f"  R² (决定系数): {metrics['R²']:.4f}")

# 主函数
def main():
    file_path = "/Users/linshangjin/pioneer-cup/lesson3_v1/predictions_best.csv"
    save_path = "/Users/linshangjin/pioneer-cup"
    
    # 加载数据
    df = load_data(file_path)
    
    # 打印数据摘要
    print_summary_statistics(df)
    
    # 绘制可视化图形
    plot_prediction_vs_target(df, save_path)
    plot_error_distribution(df, save_path)
    plot_error_by_index(df, save_path)
    plot_prediction_target_scatter(df, save_path)
    
    # 分析结果摘要
    print("\n===== 分析结果 =====")
    error_mean = df['error'].mean()
    if error_mean < 0:
        print(f"模型总体上高估了目标值，平均误差为 {error_mean:.4f}")
    else:
        print(f"模型总体上低估了目标值，平均误差为 {error_mean:.4f}")
    
    print(f"预测值与目标值的相关系数: {df['prediction'].corr(df['target']):.4f}")

if __name__ == "__main__":
    main()
